package com.xixibaby.core;

import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 重写jdk的 optional
 * 因为 JDK optional 对于空字符串  0  都是通过的
 * 可以自定义 不通过的规则
 * 加了俩个不通过规则的静态方法
 * by  tomj
 *
 */
public final class Optionals<T> {

    private static final Optionals EMPTY = new Optionals();

    private final boolean isPresent;
    private final T value;

    private Optionals(){
        this.isPresent = false;
        this.value = null;
    }

    public static Optionals empty() {
        return EMPTY;
    }

    private Optionals(T value, Predicate<T> predicate) {
        this.isPresent = Objects.nonNull(value) && predicate.test(value);
        this.value = value;
    }

    /**
     * 创建函数  允许为空  允许null
     *
     * @param value
     * @return
     */
    public static<T> Optionals<T> of(T value) {
        return new Optionals(value, v->true);
    }




    public static<T> Optionals<T> of(T value, Predicate<T> predicate) {
        return new Optionals(value,predicate);
    }

    public T getValue() {
        if (!isPresent) {
            throw new NoSuchElementException("结果不通过");
        }
        return value;
    }

    public boolean isPresent() {
        return isPresent;
    }

    public void ifPresent(Consumer<T> consumer) {
        if (isPresent){
            consumer.accept(value);
        }

    }

    /**
     * 如果条件成立的情况下 需要返回别的什么东西
     * @param consumer
     * @param <R>
     * @return
     */
    public <R> R ifPresentGet(Function<T,R> consumer) {
        if (isPresent){
            return consumer.apply(value);
        }
        return null;

    }


    public void ifNotPresent(Consumer<T> consumer) {
        if (!isPresent){
            consumer.accept(value);
        }
    }

    public  T orElse(T other) {
        return isPresent ? value : other;
    }

    public T orElseGet(Supplier<T> other) {
        return isPresent ? value : other.get();
    }

    public<X extends Throwable> T orElseThrow(Supplier<X> exceptionSupplier) throws X {
        if (isPresent) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

    @Override
    public int hashCode() {
        return isPresent ? value.hashCode() : 0;
    }

    @Override
    public String toString() {
        return isPresent
                ? String.format("StringOptional[%s]", value)
                : "StringOptional.empty";
    }


    public static boolean not0(Integer t){
        return t.intValue() != 0;
    }
    public static boolean not0(Long t){
        return t.longValue() != 0L;
    }

    public static boolean notEmpty(String str){
        return !((str == null) || (str.length() == 0));
    }


    public static void main(String[] args) {
       String s = Optionals.of("", Optionals::notEmpty).orElseThrow(NullPointerException::new);
        System.out.println(s);

        //java.util.Optionals

        //Optionals

        //OptionalInt
    }

}
